/**
 * File name: AbstractARFFBucketWriter.java Author: Willard Wang Create date:
 * Aug 25, 2013
 */
package edu.sjtu.se.prophet.io;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import edu.sjtu.se.prophet.graph.Bucket;
import edu.sjtu.se.prophet.graph.Graph;

/**
 * @author deathspeeder
 * 
 */
public abstract class AbstractARFFBucketWriter extends AbstractARFFFileWriter {
    private static Logger logger = Logger
            .getLogger(AbstractARFFBucketWriter.class);

    static class WriteDataThread extends Thread {
        Graph graph;
        StringBuffer buffer;
        AbstractARFFBucketWriter parent;

        public WriteDataThread(Graph graph, StringBuffer buffer,
                AbstractARFFBucketWriter parent) {
            this.graph = graph;
            this.buffer = buffer;
            this.parent = parent;
        }

        public void run() {
            logger.info(graph.getMeta().get("Version"));
            for (Bucket bucket : parent.getBuckets(graph)) {
                if (bucket.getData().size() == 0) {
                    logger.warn("Bucket empty, ingored!");
                    continue;
                }

                for (int i = 0; i < VALID_METRICS.length; i++) {
                    buffer.append(bucket.getAverageMetric(VALID_METRICS[i]));
                    buffer.append(",");
                }
                buffer.append(parent.getLevel(bucket
                        .getSumMetric(IOCommon.BUG_COUNT)));
                buffer.append(" % " + parent.getComment(bucket) + "\n");
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see edu.sjtu.se.prophet.io.AbstractARFFFileWriter#writeData()
     */
    @Override
    protected void writeData() throws IOException {
        br.append("@DATA\n");
        List<Thread> threads = new ArrayList<Thread>();
        List<StringBuffer> buffers = new ArrayList<StringBuffer>();
        for (Graph graph : graphs) {
            StringBuffer buffer = new StringBuffer();
            buffers.add(buffer);
            Thread t = new WriteDataThread(graph, buffer, this);
            threads.add(t);
            t.start();

        }

        for (int i = 0; i < threads.size(); i++) {
            try {
                threads.get(i).join();
            } catch (InterruptedException e) {
                logger.error("Unexpected", e);
            }
            br.append(buffers.get(i).toString());
            br.flush();
        }
    }

    // /*
    // * (non-Javadoc)
    // *
    // * @see edu.sjtu.se.prophet.io.AbstractARFFFileWriter#writeData()
    // */
    // @Override
    // protected void writeData() throws IOException {
    // br.append("@DATA\n");
    // for (Graph graph : graphs) {
    // logger.info(graph.getMeta().get("Version"));
    // for (Bucket bucket : getBuckets(graph)) {
    // if (bucket.getData().size() == 0)
    // continue;
    //
    // StringBuffer buffer = new StringBuffer();
    // for (int i = 0; i < VALID_METRICS.length; i++) {
    // buffer.append(bucket.getAverageMetric(VALID_METRICS[i]));
    // buffer.append(",");
    // }
    // buffer.append(getLevel(bucket.getSumMetric(IOCommon.BUG_COUNT)));
    // br.append(buffer.toString() + " % " + getComment(bucket) + "\n");
    // br.flush();
    // }
    // }
    // }

    /**
     * 
     * @param bucket
     * @return
     */
    protected abstract String getComment(Bucket bucket);

    /**
     * @param graph
     * @return
     */
    protected abstract List<? extends Bucket> getBuckets(Graph graph);

}
